package com.zzy.demo.sharding;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPipeline;
import redis.clients.jedis.ShardedJedisPool;
import redis.clients.jedis.ShardedJedisSentinelPool;

public class TestShard {

	private static Jedis jedis;
	private static ShardedJedis sharding;
	private static ShardedJedisPool pool;

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		JedisShardInfo jedisShardInfo = new JedisShardInfo("192.168.3.59", 6379);
	    jedisShardInfo.setPassword("654321");

		List<JedisShardInfo> shards = Arrays.asList(// new
													// JedisShardInfo("121.42.139.127",
													// 6379),
				jedisShardInfo); // 使用相同的ip:port,仅作测试
		jedis = new Jedis(jedisShardInfo);

		sharding = new ShardedJedis(shards);
		pool = new ShardedJedisPool(new JedisPoolConfig(), shards);
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		jedis.disconnect();
		sharding.disconnect();
		pool.destroy();
	}

	/**
	 * 分布式直连同步调用 //2.176 seconds 这个是分布式直接连接，并且是同步调用，每步执行都返回执行结果。类似地，还有异步管道调用。
	 */
	@Test
	public void test5shardNormal() {
		long start = System.currentTimeMillis();
		for (int i = 0; i < 1000; i++) {
			String result = sharding.set("sn" + i, "n" + i);
		}
		long end = System.currentTimeMillis();
		System.out.println("Simple@Sharing SET: " + ((end - start) / 1000.0) + " seconds");
	}

	/**
	 * 分布式直连异步调用 //0.425 seconds
	 */
	@Test
	public void test6shardpipelined() {
		ShardedJedisPipeline pipeline = sharding.pipelined();
		long start = System.currentTimeMillis();
		for (int i = 0; i < 1000; i++) {
			pipeline.set("sp" + i, "p" + i);
		}
		List<Object> results = pipeline.syncAndReturnAll();
		long end = System.currentTimeMillis();
		System.out.println("Pipelined@Sharing SET: " + ((end - start) / 1000.0) + " seconds");
	}

	/**
	 * 分布式连接池同步调用
	 * 如果，你的分布式调用代码是运行在线程中，那么上面两个直连调用方式就不合适了，因为直连方式是非线程安全的，这个时候，你就必须选择连接池调用。
	 */
	@Test
	public void test7shardSimplePool() {
		ShardedJedis one = pool.getResource();

		long start = System.currentTimeMillis();
		for (int i = 0; i < 1000; i++) {
			String result = one.set("spn" + i, "n" + i);
		}
		long end = System.currentTimeMillis();
		one.close();
		// pool.returnResource(one);
		System.out.println("Simple@Pool SET: " + ((end - start) / 1000.0) + " seconds");
	}

	/**
	 * 分布式连接池异步调用 // 0.341 seconds
	 */
	@Test
	public void test8shardPipelinedPool() {
		ShardedJedis one = pool.getResource();

		ShardedJedisPipeline pipeline = one.pipelined();

		long start = System.currentTimeMillis();
		for (int i = 0; i < 1000; i++) {
			pipeline.set("sppn" + i, "n" + i);
		}
		List<Object> results = pipeline.syncAndReturnAll(); // 异步
		long end = System.currentTimeMillis();
		one.close();
		// pool.returnResource(one);
		System.out.println("Pipelined@Pool SET: " + ((end - start) / 1000.0) + " seconds");
	}
	
	
	
	
	
	
	
	
	
    /**
     * 分布式Shard 支持主从切换
     */
	@Test
	public void testShardedJedisSentinelPool() {
		GenericObjectPoolConfig config = new GenericObjectPoolConfig();

		/**
		 * 哨兵节点   关注的  masterName       sentinel.conf   里面         sentinel monitor mymaster 192.168.3.59 6379 2
		 */
		List<String> masters = new ArrayList<String>();
		masters.add("mymaster");

		/**
		 * 哨兵节点  ip:端口号
		 */
		Set<String> sentinels = new HashSet<String>();
		sentinels.add("192.168.3.59:26379");

		ShardedJedisSentinelPool pool = new ShardedJedisSentinelPool(masters, sentinels, config,"654321");
		ShardedJedis jedis = pool.getResource();
		
		long start = System.currentTimeMillis();

		for (int i = 1; i < 1000; i++) {
			String val = jedis.set("ss" + i, "vv" + i);
			//System.out.println(jedis.get("ss" + i));
		}
		jedis.close();
		pool.destroy();
		
		long end = System.currentTimeMillis();
		System.out.println("Pipelined@Pool SET: " + ((end - start) / 1000.0) + " seconds");
	}
	
	


	
    /**
     * 分布式Shard   支持主从切换
     */
	@Test
	public void testShardedJedisSentinelPoolPipelined() {
		GenericObjectPoolConfig config = new GenericObjectPoolConfig();

		/**
		 * 哨兵节点   关注的  masterName       sentinel.conf   里面         sentinel monitor mymaster 192.168.3.59 6379 2
		 */
		List<String> masters = new ArrayList<String>();
		masters.add("mymaster");

		/**
		 * 哨兵节点  ip:端口号
		 */
		Set<String> sentinels = new HashSet<String>();
		sentinels.add("192.168.3.59:26379");

		ShardedJedisSentinelPool pool = new ShardedJedisSentinelPool(masters, sentinels, config,"654321");
		ShardedJedis jedis = pool.getResource();
		
		ShardedJedisPipeline pipeline = jedis.pipelined();
		
		long start = System.currentTimeMillis();

		for (int i = 1; i < 1000; i++) {
			pipeline.set("ss" + i, "vv" + i);
		}
		List<Object> results = pipeline.syncAndReturnAll(); // 异步
		
		jedis.close();
		pool.destroy();
		
		long end = System.currentTimeMillis();
		System.out.println("Pipelined@Pool SET: " + ((end - start) / 1000.0) + " seconds");
	}
	
	

}
